package br.com.ac.fatureweb.integration.business;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import br.com.ac.fatureweb.integration.billing.ContaVO;
import br.com.ac.fatureweb.integration.billing.FaturaVO;
import br.com.ac.fatureweb.integration.billing.LancamentoCobradoVO;
import br.com.ac.fatureweb.integration.billing.LogLeituraVO.TypeRetencao;
import br.com.ac.fatureweb.integration.billing.ProdutoVO;
import br.com.ac.fatureweb.integration.billing.ProdutoVO.EnumTypeProduto;
import br.com.ac.fatureweb.integration.billing.ValorVO;
import br.com.ac.fatureweb.integration.billing.VolumeVO;
import br.com.ac.fatureweb.integration.model.CodeBar;
import br.com.ac.fatureweb.integration.model.ConfiguracaoCalculoVO;
import br.com.ac.fatureweb.integration.model.ConfiguracaoSaaeVO;
import br.com.ac.fatureweb.integration.model.EconomiaVO;
import br.com.ac.fatureweb.integration.model.FaixaVO;
import br.com.ac.fatureweb.integration.model.ImovelVO;
import br.com.ac.fatureweb.integration.model.LancamentoFuturoVO;
import br.com.ac.fatureweb.integration.model.MensagemVO;
import br.com.ac.fatureweb.integration.model.MensagemVO.EnumTypeMensagem;
import br.com.ac.fatureweb.integration.model.OcorrenciaVO;
import br.com.ac.fatureweb.integration.model.OcorrenciaVO.EnumTypeCobranca;
import br.com.ac.fatureweb.integration.model.SaldoDebitoCreditoVO;
import br.com.ac.fatureweb.integration.model.SaldoDebitoCreditoVO.EnumTypeSaldo;
import br.com.ac.fatureweb.integration.model.TarifaSocialVO;
import br.com.ac.fatureweb.integration.model.TarifaVO;
import br.com.ac.fatureweb.integration.model.VolumeSaldo;
import br.com.ac.fatureweb.integration.utilitary.MakeCodeBar;
import br.com.ac.fatureweb.integration.utilitary.NumberUtils;
import br.com.ac.fatureweb.integration.utilitary.NumberUtils.TypeDecimal;

public class GerarFatura {

	private VolumeVO volumeAgua = null;

	public FaturaVO gerar(Long leituraAtual, Long dataLeitura,
			Long codOcorrencia, Long codLeiturista, Long leituraAnterior,
			ImovelVO imovel, ConfiguracaoCalculoVO confCalculo,
			ConfiguracaoSaaeVO configuracaoSaae,
			List<OcorrenciaVO> lstOcorrencia, List<TarifaVO> lstTarifa,
			List<FaixaVO> lstFaixa, List<TarifaSocialVO> lstTarifaSocial,
			List<MensagemVO> lstMensagem, List<EconomiaVO> lstEconomia,
			List<LancamentoFuturoVO> lstLancamento,
			List<SaldoDebitoCreditoVO> lstSaldoDebitoCredito) {

		Double valorAgua = 0D;

		TarifaSocialVO tarifaSocial = lstTarifaSocial != null
				&& !lstTarifaSocial.isEmpty() ? lstTarifaSocial.iterator()
				.next() : null;

		/*
		 * Gerar os produtos de água e esgoto.
		 */
		List<ProdutoVO> lstProduto = new ArrayList<ProdutoVO>();

		valorAgua = gerarProduto(leituraAtual, codOcorrencia, leituraAnterior,
				imovel, configuracaoSaae, tarifaSocial, lstOcorrencia,
				lstTarifa, lstFaixa, lstEconomia, lstSaldoDebitoCredito,
				valorAgua, lstProduto, dataLeitura,
				imovel.getDataLeituraAnterior());

		/*
		 * Calcular e gerar os lançamentos das taxas extras enviadas nos objetos
		 * de configuração do SAAE.
		 */
		List<LancamentoCobradoVO> lstLancamentoCobrado = calcularTaxaExtra(
				valorAgua, imovel, confCalculo);

		/*
		 * Gerar os lançamento cobrados dos serviços enviados a cobrar.
		 */
		lstLancamentoCobrado.addAll(gerarLancamentoServico(
				imovel.getInscricao(), imovel.getIdCarga(), lstLancamento));

		ContaVO conta = gerarConta(dataLeitura, codLeiturista, imovel,
				confCalculo, tarifaSocial, lstProduto, lstLancamentoCobrado,
				lstOcorrencia, lstMensagem);

		FaturaVO faturaVO = new FaturaVO(conta, lstProduto,
				lstLancamentoCobrado);

		return faturaVO;
	}

	/**
	 * Gerar o dados principais da fatura.
	 *
	 * @autor Aldivone Correia - 10/01/2015
	 * 
	 * @param dataLeitura
	 * @param codLeiturista
	 * @param imovel
	 * @param confCalculo
	 * @param tarifaSocial
	 * @param lstProduto
	 * @param lstLancamentoCobrado
	 * @param lstOcorrencia
	 * @param lstMensagem
	 * @return
	 */
	private ContaVO gerarConta(Long dataLeitura, Long codLeiturista,
			ImovelVO imovel, ConfiguracaoCalculoVO confCalculo,
			TarifaSocialVO tarifaSocial, List<ProdutoVO> lstProduto,
			List<LancamentoCobradoVO> lstLancamentoCobrado,
			List<OcorrenciaVO> lstOcorrencia, List<MensagemVO> lstMensagem) {

		Double valorConta = somarValorConta(lstProduto, lstLancamentoCobrado);

		/*
		 * Quando existir um crédito maior que o valor da conta.
		 */
		if (valorConta < 0D) {
			valorConta = 0D;
		}

		valorConta = NumberUtils.truncateValue(valorConta,
				TypeDecimal.TWO_DECIMAL);

		boolean imprimirConta = true;

		TypeRetencao typeRetencao = isImprimirConta(confCalculo, valorConta,
				lstOcorrencia, imovel);

		if (typeRetencao != null) {
			imprimirConta = false;
		}

		boolean consumidorSocial = CalcularTarifa
				.isConsumidorSocial(tarifaSocial);

		ContaVO conta = new ContaVO(imprimirConta, dataLeitura,
				new Date().getTime(), imovel.getDataVencimento(),
				consumidorSocial, codLeiturista, imovel.getInscricao(),
				imovel.getIdCarga(), valorConta, typeRetencao);

		gerarCodigoBarra(conta, imovel);

		gerarMensagem(imovel, confCalculo, conta, lstMensagem, volumeAgua);

		return conta;
	}

	/**
	 * Calcular o valor total da conta.
	 * 
	 * @autor Aldivone Correia - 10/01/2015
	 * @param lstProduto
	 * @param lstLancamentoCobrado
	 * @return
	 */
	private Double somarValorConta(List<ProdutoVO> lstProduto,
			List<LancamentoCobradoVO> lstLancamentoCobrado) {
		Double total = 0D;

		if (lstProduto != null && !lstProduto.isEmpty()) {
			for (ProdutoVO produto : lstProduto) {
				total += produto.getValor();
			}
		}

		/*
		 * No box Serviços e Tarifas quando houver serviço código 23(Credito)
		 * informar o valor negativo e diminuir ao valor da conta.
		 */
		if (lstLancamentoCobrado != null && !lstLancamentoCobrado.isEmpty()) {
			for (LancamentoCobradoVO lancamento : lstLancamentoCobrado) {
				total += lancamento.getValor();
			}
		}

		return total;
	}

	private Double gerarProduto(Long leituraAtual, Long codOcorrencia,
			Long leituraAnterior, ImovelVO imovel,
			ConfiguracaoSaaeVO configuracaoSaae, TarifaSocialVO tarifaSocial,
			List<OcorrenciaVO> lstOcorrencia, List<TarifaVO> lstTarifa,
			List<FaixaVO> lstFaixa, List<EconomiaVO> lstEconomia,
			List<SaldoDebitoCreditoVO> lstSaldoDebitoCredito, Double valorAgua,
			List<ProdutoVO> lstProduto, Long dataLeitura,
			Long dataLeituraAnterior) {

		if (imovel.isFlgFaturaAgua()) {

			Double valor = criarProdutoAgua(leituraAtual, codOcorrencia,
					leituraAnterior, imovel, configuracaoSaae, tarifaSocial,
					lstOcorrencia, lstTarifa, lstFaixa, lstEconomia,
					lstSaldoDebitoCredito, lstProduto, dataLeitura,
					dataLeituraAnterior);

			valorAgua = valor;
		}

		if (imovel.isFlgFaturaEsgoto()) {
			/*
			 * Se o  "FATURA_ESGOTO":"S" no objeto do array "FICHA" então é
			 * lançado o serviço de esgoto no percentual de "PCT_ESGOTO" em cima
			 * do valor da água.
			 */
			criarProdutoEsgoto(imovel, valorAgua, lstProduto);
		}

		return valorAgua;
	}

	private void criarProdutoEsgoto(ImovelVO imovel, Double valorAgua,
			List<ProdutoVO> lstProduto) {

		Double percentualEsgoto = imovel.getPercentualEsgoto();

		if (percentualEsgoto != null) {

			EnumTypeProduto typeProduto = EnumTypeProduto.ESGOTO;

			Double valor = NumberUtils.arredondarValor(valorAgua
					* (percentualEsgoto / 100));

			ProdutoVO produto = new ProdutoVO(imovel.getInscricao(),
					imovel.getIdCarga(), typeProduto.getCodigo(),
					typeProduto.name(), 0L, 0L, valor, imovel.getTarifa(),
					false, null, null);

			lstProduto.add(produto);
		}
	}

	private Double criarProdutoAgua(Long leituraAtual, Long codOcorrencia,
			Long leituraAnterior, ImovelVO imovel,
			ConfiguracaoSaaeVO configuracaoSaae, TarifaSocialVO tarifaSocial,
			List<OcorrenciaVO> lstOcorrencia, List<TarifaVO> lstTarifa,
			List<FaixaVO> lstFaixa, List<EconomiaVO> lstEconomia,
			List<SaldoDebitoCreditoVO> lstSaldoDebitoCredito,
			List<ProdutoVO> lstProduto, Long dataLeitura,
			Long dataLeituraAnterior) {

		EnumTypeCobranca typeCobrancaConsumoZerado = EnumTypeCobranca
				.valueOf(configuracaoSaae.getFatConszerado());

		Long minimoTarifa = CalcularTarifa.getMinimoTarifa(imovel.getTarifa(),
				lstFaixa);

		EnumTypeProduto typeProduto = EnumTypeProduto.AGUA;

		VolumeVO consumoAgua = new CalcularConsumo(imovel,
				typeProduto.ordinal()).calcular(leituraAtual, leituraAnterior,
				codOcorrencia, imovel.getConsumoMedio(),
				imovel.isTemHidrometro(), typeCobrancaConsumoZerado,
				minimoTarifa, lstSaldoDebitoCredito, lstOcorrencia);

		consumoAgua.setDiasConsumo(calcularDiasConsumo(dataLeitura,
				dataLeituraAnterior));

		List<ValorVO> lstValorTarifa = new CalcularTarifa(imovel,
				typeProduto.ordinal()).calcular(
				consumoAgua.getConsumoFaturado(), imovel.getTarifa(),
				lstTarifa, lstFaixa, tarifaSocial, lstEconomia);

		Double valor = somarTarifa(lstValorTarifa);

		ProdutoVO produto = new ProdutoVO(imovel.getInscricao(),
				imovel.getIdCarga(), typeProduto.getCodigo(),
				typeProduto.name(), consumoAgua.getConsumoFaturado(),
				consumoAgua.getConsumoMedido(), valor, imovel.getTarifa(),
				imovel.isTemHidrometro(), consumoAgua, lstValorTarifa);

		volumeAgua = consumoAgua;

		lstProduto.add(produto);

		return valor;
	}

	private Integer calcularDiasConsumo(Long dataLeitura,
			Long dataLeituraAnterior) {
		if (dataLeitura != null && dataLeituraAnterior != null) {
			int MILLIS_IN_DAY = 86400000;

			Calendar dtLeitura = Calendar.getInstance(new Locale("pt", "BR"));
			dtLeitura.setTimeInMillis(dataLeitura);
			dtLeitura.set(Calendar.MILLISECOND, 0);
			dtLeitura.set(Calendar.SECOND, 0);
			dtLeitura.set(Calendar.MINUTE, 0);
			dtLeitura.set(Calendar.HOUR_OF_DAY, 0);

			Calendar dtLeituraAnterior = Calendar.getInstance(new Locale("pt",
					"BR"));
			dtLeituraAnterior.setTimeInMillis(dataLeituraAnterior);
			dtLeituraAnterior.set(Calendar.MILLISECOND, 0);
			dtLeituraAnterior.set(Calendar.SECOND, 0);
			dtLeituraAnterior.set(Calendar.MINUTE, 0);
			dtLeituraAnterior.set(Calendar.HOUR_OF_DAY, 0);

			return (int) ((dtLeitura.getTimeInMillis() - dtLeituraAnterior
					.getTimeInMillis()) / MILLIS_IN_DAY);
		}
		return null;
	}

	/**
	 * No box Serviços e Tarifas quando houver serviço código 23(Credito)
	 * informar o valor negativo e diminuir ao valor da conta.
	 * 
	 * @param inscricao
	 * @param idCarga
	 * @param lstLancamento
	 * @return
	 */
	private List<LancamentoCobradoVO> gerarLancamentoServico(Long inscricao,
			Long idCarga, List<LancamentoFuturoVO> lstLancamento) {

		List<LancamentoCobradoVO> lstLancamentos = new ArrayList<LancamentoCobradoVO>();

		if (lstLancamento != null && !lstLancamento.isEmpty()) {

			for (LancamentoFuturoVO lancamento : lstLancamento) {
				LancamentoCobradoVO lancamentoCobrado = new LancamentoCobradoVO();

				lancamentoCobrado.setCodServico(lancamento.getCodServico());
				lancamentoCobrado.setDescricao(lancamento.getDescricao());
				lancamentoCobrado.setParcela(lancamento.getParcela());

				/*
				 * No box Serviços e Tarifas quando houver serviço código
				 * 23(Credito) informar o valor negativo e diminuir ao valor da
				 * conta.
				 */
				Double valor = lancamento.getValor();
				if (lancamento != null
						&& lancamento.getCodServico().equals(23L)) {
					valor = lancamento.getValor() * -1;
				}
				lancamentoCobrado.setValor(valor);

				lancamentoCobrado.setIdCarga(idCarga);
				lancamentoCobrado.setInscricao(inscricao);

				lstLancamentos.add(lancamentoCobrado);
			}
		}

		return lstLancamentos;
	}

	private Double somarTarifa(List<ValorVO> lstValorTarifa) {
		Double total = 0D;

		if (lstValorTarifa != null && !lstValorTarifa.isEmpty()) {
			for (ValorVO valorVO : lstValorTarifa) {
				total += valorVO.getValor();
			}
		}

		return total;
	}

	/**
	 * Calcular e gerar os lançamentos das taxas extras enviadas nos objetos de
	 * configuração do SAAE.
	 * 
	 * @autor Aldivone Correia - 10/01/2015
	 * 
	 * @param valorAgua
	 * @param imovel
	 * @param confCalculo
	 * @return
	 */
	private List<LancamentoCobradoVO> calcularTaxaExtra(Double valorAgua,
			ImovelVO imovel, ConfiguracaoCalculoVO confCalculo) {

		List<LancamentoCobradoVO> lstLancamentos = new ArrayList<LancamentoCobradoVO>();

		/*
		 * Taxa1 – se houver, e em sobral tem;
		 * 
		 * Taxa2 – se houver, sobral não possui, mas se quiserem já estará
		 * preparado
		 * 
		 * CSM_CONSHIDRO – serviço que pode ser lançado apenas para quem possui
		 * hidrômetro.
		 * 
		 * objeto "CALCULO"  campo "FLG_TAXA1" = 1(percentual) valor
		 * "VAL_TAXA1":20 = 20% no valor da água.
		 * 
		 * Serviço extra = 20% no valor da água = 113,38 113,38 * 0.2 = 22,676 =
		 * 22,68.
		 * 
		 * se o "ISENTO_TAXA1": for “N” então este imóvel receberá o serviço
		 * taxa1, esta    Mesma regra aplicasse ao "ISENTO_CONSHID" e
		 * "ISENTO_TAXA2"
		 */
		Integer flgConsertoHidro = confCalculo.getCsmConshidro();

		if (flgConsertoHidro != null && !imovel.isIsentoConshid()
				&& imovel.isTemHidrometro()) {

			LancamentoCobradoVO taxaExtraConsercaoHidrometro = calcularLancamentoTaxaExtra(
					996L, confCalculo.getDesConshidro(),
					confCalculo.getValConshidro(), flgConsertoHidro, valorAgua,
					imovel);

			if (taxaExtraConsercaoHidrometro != null) {
				lstLancamentos.add(taxaExtraConsercaoHidrometro);
			}
		}

		Integer flgTaxa1 = confCalculo.getFlgTaxa1();

		if (flgTaxa1 != null && !imovel.isIsentoTaxa1()) {

			LancamentoCobradoVO taxaExtra1 = calcularLancamentoTaxaExtra(997L,
					confCalculo.getDesTaxa1(), confCalculo.getValTaxa1(),
					flgTaxa1, valorAgua, imovel);

			if (taxaExtra1 != null) {
				lstLancamentos.add(taxaExtra1);
			}
		}

		Integer flgTaxa2 = confCalculo.getFlgTaxa2();

		if (flgTaxa2 != null && !imovel.isIsentoTaxa2()) {

			LancamentoCobradoVO taxaExtra2 = calcularLancamentoTaxaExtra(998L,
					confCalculo.getDesTaxa2(), confCalculo.getValTaxa2(),
					flgTaxa2, valorAgua, imovel);

			if (taxaExtra2 != null) {
				lstLancamentos.add(taxaExtra2);
			}
		}

		return lstLancamentos;
	}

	private LancamentoCobradoVO calcularLancamentoTaxaExtra(Long codServico,
			String descricao, Double valorTaxa, Integer flgTaxa1,
			Double valorAgua, ImovelVO imovel) {

		Double valorTaxaCalc = null;

		EnumTypeTaxa typeTaxa = EnumTypeTaxa.valueOF(flgTaxa1);

		if (typeTaxa != null) {

			switch (typeTaxa) {

			case PERCENTUAL: {
				valorTaxaCalc = NumberUtils.arredondarValorTaxaExtra(valorAgua
						* (valorTaxa / 100));
				break;
			}
			case VALOR:
				valorTaxaCalc = valorTaxa;
				break;
			}
		}

		if (valorTaxaCalc != null) {
			LancamentoCobradoVO lancamentoCobrado = new LancamentoCobradoVO();

			lancamentoCobrado.setCodServico(codServico);
			lancamentoCobrado.setDescricao(descricao);
			lancamentoCobrado.setValor(valorTaxaCalc);

			lancamentoCobrado.setIdCarga(imovel.getIdCarga());
			lancamentoCobrado.setInscricao(imovel.getInscricao());

			return lancamentoCobrado;
		}

		return null;
	}

	/**
	 * Regras determinar se a conta deverá ser impressa ou não.
	 * 
	 * @param confCalculo
	 * @param valorConta
	 * @param lstOcorrenciaVO
	 * @param imovel
	 * 
	 * @return
	 */
	private TypeRetencao isImprimirConta(ConfiguracaoCalculoVO confCalculo,
			Double valorConta, List<OcorrenciaVO> lstOcorrenciaVO,
			ImovelVO imovel) {
		/*
		 * "CALCULO"."VAL_MINIMO":"0", <- valor mínimo para impressão da conta.
		 */
		// if (confCalculo != null && confCalculo.getValMinimo() != null
		// && confCalculo.getValMinimo().intValue() > 0
		// && valorConta < confCalculo.getValMinimo()) {
		// return TypeRetencao.PARAMETRO;
		// }

		if (volumeAgua != null && volumeAgua.getCodOcorrencia1() != null) {
			OcorrenciaVO ocorrencia = CalcularConsumo.getOcorrencia(
					lstOcorrenciaVO, volumeAgua.getCodOcorrencia1());

			if (ocorrencia != null && !ocorrencia.isFlgEmitirConta()) {
				return TypeRetencao.OCORRENCIA;
			}
		}

		/*
		 * A inscrição 250524 emitiu conta , quando no campo ind_emitirconta
		 * (tabela imovel) estar FALSE
		 */
		if (!imovel.isFlgEmitirConta()) {
			return TypeRetencao.IMOVEL;
		}

		return null;
	}

	/**
	 * Gerar o complemento do código de barra da conta.
	 * 
	 * @autor Aldivone Correia - 10/01/2015
	 * @param conta
	 */
	private void gerarCodigoBarra(ContaVO conta, ImovelVO imovelVO) {

		CodeBar codeBar = MakeCodeBar.calc(imovelVO.getCodigoBarras(),
				conta.getValorConta());

		conta.setCodigoBarra(codeBar.getCodigoBarra());

		conta.setCodigoBarra1(codeBar.getDscCodigoBarra1());
		conta.setCodigoBarra2(codeBar.getDscCodigoBarra2());
		conta.setCodigoBarra3(codeBar.getDscCodigoBarra3());
		conta.setCodigoBarra4(codeBar.getDscCodigoBarra4());

		conta.setDigitoCodigoBarra1(codeBar.getNumDigitoCodigoBarra1()
				.toString());
		conta.setDigitoCodigoBarra2(codeBar.getNumDigitoCodigoBarra2()
				.toString());
		conta.setDigitoCodigoBarra3(codeBar.getNumDigitoCodigoBarra3()
				.toString());
		conta.setDigitoCodigoBarra4(codeBar.getNumDigitoCodigoBarra4()
				.toString());
	}

	public static void main(String[] args) {

		CodeBar calc = MakeCodeBar.calc(
				"82200000215048200974123220154098290108605940", 21504.82D);

		System.out.println(calc);
	}

	/**
	 * Gerar mensagem para impressão na conta.
	 * 
	 * @autor Aldivone Correia - 10/01/2015
	 * @param confCalculoVO
	 * @param conta
	 * @param volumeAgua
	 */
	private void gerarMensagem(ImovelVO imovel,
			ConfiguracaoCalculoVO confCalculoVO, ContaVO conta,
			List<MensagemVO> lstMensagem, VolumeVO volumeAgua) {

		List<String> lstMensagemConta = new ArrayList<String>();

		lstMensagemConta.add(imovel.getMesesDebito());

		/*
		 * 4. Mensagens originadas no faturamento.
		 */
		gerarMensagemFaturamento(lstMensagemConta);

		/*
		 * Mensagens – Regras de prioridade - SAAE.
		 */
		gerarMensagemRecebidaSaae(lstMensagem, lstMensagemConta);

		/*
		 * Setar as mensagem encontradas na conta para impressão na fatura.
		 */
		setMensagemConta(conta, lstMensagemConta);
	}

	/**
	 * 4. Mensagens originadas no faturamento:
	 * 
	 *  Saldo tipo “M”, o consumo será subtraído do consumo mensal e este
	 * procedimento deve ser complementado gerando-se uma mensagem individual de
	 * “Foi subtraído 99m3 do seu consumo, proveniente de saldo em metros
	 * cúbicos.”;
	 * 
	 *  Saldo tipo “L”, o consumo será subtraído do consumo mensal e este
	 * procedimento deve ser complementado gerando-se uma mensagem individual de
	 * “Foi subtraído 99m3 do seu consumo, proveniente de Leituras não
	 * Realizadas.”;
	 * 
	 * @autor Aldivone Correia - 11/01/2015
	 * @param lstMensagemConta
	 */
	@SuppressWarnings("incomplete-switch")
	private void gerarMensagemFaturamento(List<String> lstMensagemConta) {
		List<VolumeSaldo> lstVolumeSaldo = volumeAgua.getLstVolumeSaldo();
		if (lstVolumeSaldo != null && !lstVolumeSaldo.isEmpty()) {

			for (VolumeSaldo volumeSaldo : lstVolumeSaldo) {

				EnumTypeSaldo typeSaldo = volumeSaldo.getTypeSaldo();

				switch (typeSaldo) {
				case L: {
					lstMensagemConta.add("FOI SUBTRAIDO "
							+ volumeSaldo.getVolumeDeduzido().toString()
							+ "M3 DO SEU CONSUMO,"
							+ " PROVENIENTE DE LEITURAS NAO REALIZADAS.");
					break;
				}
				case M: {
					lstMensagemConta.add("FOI SUBTRAIDO "
							+ volumeSaldo.getVolume().toString()
							+ "M3 DO SEU CONSUMO,"
							+ " PROVENIENTE DE SALDO EM METROS CUBICOS.");
					break;
				}
				}
			}
		}
	}

	/**
	 * Mensagens – Regras de prioridade:
	 * 
	 *  Mensagem tipo zero, esta mensagem abrangerá todas as contas impressas;
	 * 
	 *  Mensagem tipo um, abrangerá todas as ligações que tenham o código da
	 * localidade igual ao código da mensagem e terá prioridade sobre a mensagem
	 * Geral (tipo zero);
	 * 
	 *  Mensagem tipo dois, abrangerá todas as ligações que tenham o código do
	 * distrito igual ao código da mensagem e terá prioridade sobre as mensagens
	 * da Localidade e em Geral;
	 * 
	 *  Mensagem tipo três, abrangerá todas as ligações que tenham o código do
	 * setor igual ao código da mensagem e terá prioridade sobre as mensagens de
	 * Distritos, Localidades e em Geral,
	 * 
	 *  Mensagem tipo quatro, será especifica para a ligação e terá prioridade
	 * sobre todas as mensagens anteriores,
	 * 
	 * @autor Aldivone Correia - 11/01/2015
	 * @param lstMensagem
	 * @param lstMensagemConta
	 */
	private void gerarMensagemRecebidaSaae(List<MensagemVO> lstMensagem,
			List<String> lstMensagemConta) {
		if (lstMensagem != null && !lstMensagem.isEmpty()) {

			for (MensagemVO mensagem : lstMensagem) {
				Long codMensagem = mensagem.getCodigo();

				if (codMensagem != null) {
					EnumTypeMensagem typeMensagem = EnumTypeMensagem
							.valueOf(codMensagem.intValue());

					if (typeMensagem != null) {

						switch (typeMensagem) {
						case GERAL: {
							lstMensagemConta.add(mensagem.getLinha1());
							break;
						}
						case LOCALIDADE: {
							break;
						}
						case DISTRITO: {
							break;
						}
						case SETOR: {
							break;
						}
						case IMOVEL: {
							break;
						}
						}
					}
				}
			}
		}
	}

	private void setMensagemConta(ContaVO conta, List<String> lstMensagemConta) {
		if (!lstMensagemConta.isEmpty()) {
			for (int index = 0; index < lstMensagemConta.size(); index++) {
				switch (index) {
				case 0: {
					conta.setMensagem1(lstMensagemConta.get(index));
					break;
				}
				case 1: {
					conta.setMensagem2(lstMensagemConta.get(index));
					break;
				}
				case 2: {
					conta.setMensagem3(lstMensagemConta.get(index));
					break;
				}
				case 3: {
					conta.setMensagem4(lstMensagemConta.get(index));
					break;
				}
				case 4: {
					conta.setMensagem5(lstMensagemConta.get(index));
					break;
				}
				case 5: {
					conta.setMensagem6(lstMensagemConta.get(index));
					break;
				}
				}
			}
		}
	}

	public enum EnumTypeTaxa {
		PERCENTUAL(1), VALOR(2);

		private int codigo;

		private EnumTypeTaxa(int codigo) {
			this.codigo = codigo;
		}

		public static EnumTypeTaxa valueOF(int codigo) {
			EnumTypeTaxa[] values = EnumTypeTaxa.values();

			for (EnumTypeTaxa typeTaxa : values) {
				if (typeTaxa.codigo == codigo) {
					return typeTaxa;
				}
			}

			return null;
		}

	}

}
